﻿using HtmlAgilityPack;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Xamarin.Essentials;
using Xamarin.Forms;
using HtmlDocument = HtmlAgilityPack.HtmlDocument;

namespace Scores
{
    public partial class MainPage : ContentPage
    {
        static readonly HttpClient client = new HttpClient();
        private string mainpath = "";

        private string studentId;

        List<Course> courses = new List<Course>();
        public List<CourseGrade> coursegrade = new List<CourseGrade>();
        public MainPage()
        {
            InitializeComponent();
            InitializePageAsync();
            //Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

        }
        private async void InitializePageAsync()
        {
            // 在这里执行需要异步操作的代码
            await main();
        }

        private async Task main()
        {
            // 请求权限
            var status = await Permissions.RequestAsync<Permissions.StorageWrite>();

            if (status == PermissionStatus.Granted)
            {
                // 获取应用程序的特定存储目录
                string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);

                // 创建第一级子目录
                string firstLevelSubFolderPath = Path.Combine(folderPath, "kebaiodata");

                if (!Directory.Exists(firstLevelSubFolderPath))
                {
                    Directory.CreateDirectory(firstLevelSubFolderPath);
                }

                mainpath = firstLevelSubFolderPath;

                // 创建第二级子目录
                string secondLevelSubFolderPath = Path.Combine(firstLevelSubFolderPath, "credentials");

                if (!Directory.Exists(secondLevelSubFolderPath))
                {
                    Directory.CreateDirectory(secondLevelSubFolderPath);
                }

                // 添加自定义选项数据
                List<string> userNames = new List<string>
                {
                    "我选输入"
                };


                // 获取保存的用户名
                string[] files = Directory.GetFiles(secondLevelSubFolderPath, "*_credentials.txt");
                //List<string> userNames = new List<string>();

                foreach (string file in files)
                {
                    string fileName = Path.GetFileNameWithoutExtension(file).Split('_')[0];
                    userNames.Add(fileName);
                }

                // 绑定数据到 ListView
                foreach (string option in userNames)
                {
                    comboBox3Picker.Items.Add(option);
                    // 设置默认选项
                    comboBox3Picker.SelectedIndex = 1;
                }


                string fileNamess = mainpath + "//myAllScore.html";
                if (!File.Exists(fileNamess))
                {
                    await DisplayAlert("提示", "能不能先输账号密码获取？", "能！");

                    return;
                }

                Button_Clicked_1(this, null);

            }
            else
            {
                return;
            }
        }

        private void LoadCredentialsFromFile(string uid)
        {
            string path = mainpath + $"/credentials/{uid}_credentials.txt"; // 文件路径。

            if (File.Exists(path))
            {
                using (FileStream fs = new FileStream(path, FileMode.Open))
                {
                    byte[] iv = new byte[16];
                    byte[] key = new byte[32]; // AES 密钥长度为 256 位（32 字节）

                    fs.Read(iv, 0, iv.Length);
                    fs.Read(key, 0, key.Length);

                    using (Aes aesAlg = Aes.Create())
                    using (ICryptoTransform decryptor = aesAlg.CreateDecryptor(key, iv))
                    using (CryptoStream csDecrypt = new CryptoStream(fs, decryptor, CryptoStreamMode.Read))
                    using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                    {
                        string username = srDecrypt.ReadLine();
                        string password = srDecrypt.ReadLine();

                        // 使用解密后的凭据
                        textBox3.Text = username;
                        textBox2.Text = password;
                        textBox2.IsEnabled = false;
                    }
                }
            }
        }
        public async Task GetLoginDataAsync(Dictionary<string, string> loginData)
        {
            var response = await client.GetAsync("http://class.seig.edu.cn:7001/sise/login.jsp");

            if (response.IsSuccessStatusCode)
            {

                var htmlContent = await response.Content.ReadAsStringAsync();
                var htmlDocument = new HtmlDocument();
                htmlDocument.LoadHtml(htmlContent);

                var inputElements = htmlDocument.DocumentNode.SelectNodes("//input[@type='hidden']");

                if (inputElements != null)
                {
                    foreach (var inputElement in inputElements)
                    {
                        var nameAttribute = inputElement.GetAttributeValue("name", "");
                        var valueAttribute = inputElement.GetAttributeValue("value", "");

                        if (!string.IsNullOrEmpty(nameAttribute) && !string.IsNullOrEmpty(valueAttribute))
                        {
                            // Console.WriteLine("name: " + nameAttribute + ", value: " + valueAttribute);
                            loginData.Add(nameAttribute, valueAttribute);
                        }
                    }
                }
                else
                {
                    //弹出提示框
                    await DisplayAlert("提示", "获取隐藏字段失败", "确定");
                }
            }
            else
            {
                await DisplayAlert("提示", "HTTP请求失败：" + response.StatusCode, "确定");
            }
        }

        public async Task<string> PerformLoginAsync(Dictionary<string, string> loginData)
        {
            //await client.PostAsync("http://class.seig.edu.cn:7001/sise/common/logout.jsp", loginContent);
            //先注销
            var logoutContent = new FormUrlEncodedContent(loginData);
            await client.PostAsync("http://class.seig.edu.cn:7001/sise/common/logout.jsp", logoutContent);

            var loginContent = new FormUrlEncodedContent(loginData);
            var loginResponse = await client.PostAsync("http://class.seig.edu.cn:7001/sise/login_check_login.jsp", loginContent);

            // Console.WriteLine("Status Code: " + loginResponse.StatusCode);
            string loginContents = await loginResponse.Content.ReadAsStringAsync();
            // Console.WriteLine(loginContents);

            if (!loginResponse.IsSuccessStatusCode)
            {
                await DisplayAlert("提示", "登录失败", "确定");

            }

            return loginContents;
        }

        public void SaveCredentialsToFile(string username, string password)
        {
            string path = mainpath + "/credentials/" + username + "_credentials.txt"; // 文件路径。

            using (FileStream fs = new FileStream(path, FileMode.Create))
            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.GenerateKey();
                aesAlg.GenerateIV();

                byte[] key = aesAlg.Key;
                byte[] iv = aesAlg.IV;

                // 将 IV 和密钥写入文件。
                fs.Write(iv, 0, iv.Length);
                fs.Write(key, 0, key.Length);

                using (ICryptoTransform encryptor = aesAlg.CreateEncryptor(key, iv))
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    {
                        swEncrypt.WriteLine(username);
                        swEncrypt.WriteLine(password);
                    }

                    byte[] encryptedData = msEncrypt.ToArray();

                    // 确保在 msEncrypt 的作用域内写入加密数据。
                    fs.Write(encryptedData, 0, encryptedData.Length);
                }
            }
        }

        public async Task FetchJSPPageAsync1(string url)
        {
            var pageResponse = await client.GetAsync(url);

            if (pageResponse.IsSuccessStatusCode)
            {
                string pageContent = await pageResponse.Content.ReadAsStringAsync();
                // Console.WriteLine(pageContent);
                string fileName = mainpath + "//myScoreindex.html";
                System.IO.File.WriteAllText(fileName, pageContent);
            }
            else
            {
                throw new Exception("加载JSP页面失败");
            }
        }

        public async Task FetchJSPPageAsync(string url)
        {
            var pageResponse = await client.GetAsync(url);

            if (pageResponse.IsSuccessStatusCode)
            {
                string pageContent = await pageResponse.Content.ReadAsStringAsync();
                // Console.WriteLine(pageContent);
                string fileName = mainpath + "//myScore.html";
                File.WriteAllText(fileName, pageContent);
            }
            else
            {
                throw new Exception("加载JSP页面失败");
            }
        }


        private async void Button_Clicked_1(object sender, EventArgs e)
        {
            coursegrade = new List<CourseGrade>();
            courses = new List<Course>();
            // 定义文件所在的目录
            string directoryPath = mainpath;

            // 要排除删除的文件列表
            string[] filesToExclude = {
                "courseInfo.json",
                "nullschedule.json"
            };

            // 获取目录中的所有文件列表
            string[] filesInDirectory = Directory.GetFiles(directoryPath);

            // 遍历目录中的文件
            foreach (string filePath in filesInDirectory)
            {
                // 获取不带路径的文件名
                string fileName = Path.GetFileName(filePath);

                // 检查是否应该排除文件的删除
                if (!filesToExclude.Contains(fileName))
                {
                    // 删除文件
                    File.Delete(filePath);
                }
            }



            //禁用getSchBtn
            getSchBtn.IsEnabled = false;

            getSchBtn.Text = "获取中";

            string uid = textBox3.Text;
            string password = textBox2.Text;
            var loginData = new Dictionary<string, string>
            {
                { "username", uid },
                { "password", password },
            };
            progressBar.Progress = 0;
            MypgBar(5);
            //等待0.5秒



            // 获取登录页面并解析隐藏字段
            await GetLoginDataAsync(loginData);
            MypgBar(5);


            string ret = await PerformLoginAsync(loginData);
            // 发送登录请求
            if (!ret.Contains("index.jsp"))
            {
                Match match = Regex.Match(ret, "messages=(.*?)(?=')");

                if (match.Success)
                {
                    string extractedMessage = match.Groups[1].Value;
                    await DisplayAlert("提示", extractedMessage, "确定");
                    getSchBtn.IsEnabled = true;
                    getSchBtn.Text = "获取/更新成绩";
                }
            }
            else
            {
                MypgBar(5);

                if (checkBox1.IsToggled)
                {
                    SaveCredentialsToFile(uid, password);
                }
                // 获取id
                string url1 = "http://class.seig.edu.cn:7001/sise/module/student_states/student_select_class/main.jsp";
                await FetchJSPPageAsync1(url1);
                MypgBar(5);


                // 获取当前学期课程平时分页面
                string url = "http://class.seig.edu.cn:7001/sise/module/commonresult/index.jsp";
                await FetchJSPPageAsync(url);
                MypgBar(5);


                //获取成绩
                await scrscore();

                //获取总成绩
                await SavePageAllScore();

                //将对象coursegrade输出为json文件
                SaveCourseGradeToFile(coursegrade);

                getSchBtn.Text = "获取/更新成绩";

                //await DisplayAlert("提示", "获取成功", "确定");

                getSchBtn.IsEnabled = true;

                time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                // 跳转新页面
                await Navigation.PushAsync(new ScrScore() { Title = studentname + "'s 成绩" });

            }
        }

        public static string time = "";

        public void SaveCourseGradeToFile(List<CourseGrade> coursegrade)
        {
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(coursegrade);
            string fileName = mainpath + "//myCourseGrade.json";
            File.WriteAllText(fileName, json);
        }

        public string studentname;

        public async Task SavePageAllScore()
        {
            string url = "http://class.seig.edu.cn:7001/SISEWeb/pub/course/courseViewAction.do?method=doMain&studentid=" + studentId + "=";
            var pageResponse = await client.GetAsync(url);

            if (pageResponse.IsSuccessStatusCode)
            {
                string pageContent = await pageResponse.Content.ReadAsStringAsync();

                string fileName = mainpath + "//myAllScore.html";
                File.WriteAllText(fileName, pageContent);
                Allscore(pageContent);
                string pageContent1 = Regex.Replace(pageContent, @"[\r\t\n]", "");
                // 使用正则表达式匹配指定的 td 标签，允许包含换行和空格字符
                string pattern = @"姓名</span> ：</td><td height=""16"" class=""td_left"">\s*<div align=""left"">\s*([\u4e00-\u9fa5]+)\s*</div>\s*</td>";
                MatchCollection matches = Regex.Matches(pageContent1, pattern, RegexOptions.Singleline);

                // 提取匹配项中的值
                foreach (Match match in matches)
                {
                    studentname = match.Groups[1].Value.Trim();
                }
            }
            else
            {
                throw new Exception("加载JSP页面失败");
            }
        }

        private void Allscore(string pageContent)
        {
            // 遍历coursegrade
            progressBar.Progress = 0;
            getSchBtn.Text = "获取中";
            foreach (var c in coursegrade)
            {
                string[] strArray = c.CourseName.Split(' ');
                string courseid = strArray[2];
                string pattern = $@"<tr class=""(?:even|odd)"">(?:(?!<tr class=""(?:even|odd)"">).)*?<td>{courseid}</td>(?:(?!<tr class=""(?:even|odd)"">).)*?</tr>";
                Match match = Regex.Match(pageContent, pattern, RegexOptions.Singleline);
                if (match.Success)
                {
                    string matchedContent = match.Value;

                    // 在匹配的内容中查找倒数第4个<td>标签的值
                    MatchCollection tdMatches = Regex.Matches(matchedContent, @"<td[^>]*>(.*?)</td>");

                    if (tdMatches.Count >= 4)
                    {
                        string gradeValue = tdMatches[tdMatches.Count - 4].Groups[1].Value;
                        // 插入总成绩
                        if (gradeValue.Contains("在读")) { gradeValue = "无"; }
                        c.TotalGrade = gradeValue;
                    }
                }
                MypgBar(coursegrade.Count);

            }
        }




        public async Task scrscore()
        {
            try
            {
                // 读取myScore.html文件的内容
                string htmlContent = File.ReadAllText(mainpath + "//myScore.html");

                // 使用正则表达式匹配课程名称和超链接
                string pattern = @"<a\s+href\s*=\s*'([^']+)'\s+target='showdetail'>([^<]+)<\/a>";
                MatchCollection matches = Regex.Matches(htmlContent, pattern);

                // 提取匹配结果
                progressBar.Progress = 0;
                getSchBtn.Text = "获取中";
                foreach (Match match in matches)
                {
                    string link = match.Groups[1].Value;
                    string courseName = match.Groups[2].Value;

                    // 创建课程对象并添加到列表中
                    Course course = new Course
                    {
                        Name = courseName,
                        Link = link
                    };

                    courses.Add(course);
                    MypgBar(matches.Count);

                }

                MatchCollection matchesid = Regex.Matches(
                    File.ReadAllText(mainpath + "//myScoreindex.html"),
                    @"SISEWeb/pub/course/courseViewAction\.do\?method=doMain&studentid=(.+)=");

                // 提取匹配结果
                foreach (Match match in matchesid)
                {
                    studentId = match.Groups[1].Value;
                }
            }
            catch (Exception ex)
            {
                await DisplayAlert("提示", "发生异常: " + ex.Message, "确定");
            }
            progressBar.Progress = 0;

            getSchBtn.Text = "获取中";
            foreach (var course in courses)//遍历课程列表获取总成绩
            {
                await FetchAndSavePageAsync(course);
                MypgBar(courses.Count);

            }

        }
        private async Task FetchAndSavePageAsync(Course course)
        {
            string url = "http://class.seig.edu.cn:7001/sise/module/commonresult/" + course.Link;
            var pageResponse = await client.GetAsync(url);

            if (pageResponse.IsSuccessStatusCode)
            {
                string pageContent = await pageResponse.Content.ReadAsStringAsync();
                // Console.WriteLine(pageContent);
                onescore(pageContent);
            }
            else
            {
                throw new Exception("加载JSP页面失败");
            }
        }

        private void onescore(string pageContent)
        {
            // 使用 HtmlAgilityPack 解析 HTML
            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(pageContent);

            // 查找所有的表格
            List<List<List<string>>> tablesData = new List<List<List<string>>>();
            //var tableNodes = doc.DocumentNode.SelectNodes("//table");
            HtmlNodeCollection nodes = null;

            if (doc.DocumentNode.SelectSingleNode("//tbody") != null)
            {
                nodes = doc.DocumentNode.SelectNodes("//tbody");
            }
            else
            {
                nodes = doc.DocumentNode.SelectNodes("//table");
            }
            if (nodes != null)
            {
                foreach (HtmlNode tableNode in nodes)
                {
                    List<List<string>> table = new List<List<string>>();
                    // 遍历表格的行
                    HtmlNodeCollection rowNodes = tableNode.SelectNodes("tr");
                    if (rowNodes != null)
                    {
                        foreach (HtmlNode rowNode in rowNodes)
                        {
                            List<string> row = new List<string>();
                            // 遍历行的单元格
                            HtmlNodeCollection cellNodes = rowNode.SelectNodes("td");
                            if (cellNodes != null)
                            {
                                foreach (HtmlNode cellNode in cellNodes)
                                {
                                    string text = cellNode.InnerText.Trim();
                                    text = Regex.Replace(text, @"\s+", " "); // 仅将连续的空白替换为单个空格
                                    text = Regex.Replace(text, @"&nbsp;", " ");
                                    row.Add(text);
                                }
                            }
                            table.Add(row);
                        }
                    }
                    tablesData.Add(table);
                }
            }
            //获取课程信息
            List<List<string>> table1 = tablesData[0];
            List<List<string>> table3 = tablesData[2];
            List<List<string>> table4 = tablesData[4];
            //删掉表头
            table3.RemoveAt(0);
            double sum = 0.0;
            int columnIndex = 0;
            bool flag = true;
            foreach (List<string> row in table3)
            {
                double temp = 0.0;
                double maxcores = 0.0;
                foreach (string cell in row)
                {
                    if (columnIndex == 1)
                    {
                        temp = double.Parse(Regex.Replace(cell, @"%", ""));
                    }
                    if (columnIndex == 2)
                    {
                        maxcores = double.Parse(cell);
                    }
                    if (temp != maxcores)
                    {
                        //如果是最后一列，累加
                        if (columnIndex == row.Count - 1)
                        {
                            if (table3.IndexOf(row) != table3.Count - 1)
                            {
                                sum += double.Parse(cell) * temp / 100;
                                sum = Math.Round(sum, 1);
                            }
                            else
                            {
                                sum += double.Parse(cell);
                                sum = Math.Round(sum, 1);
                            }
                        }
                    }
                    else
                    {
                        if (columnIndex == row.Count - 1)
                        {
                            sum += cell == " " ? 0.0 : double.Parse(cell);
                            if (sum == 0.0)
                            {
                                flag = false;
                            }
                        }
                    }
                    columnIndex++; // 增加列索引
                }
                columnIndex = 0; // 重置列索引，以便下一行开始
            }
            string courseName = table1[0][0];

            string attendanceGrade = !flag ? "无" : sum.ToString();

            string attendanceWeight = table4[0][2];

            // 创建CourseGrade对象并保存信息
            CourseGrade courseGrade = new CourseGrade
            {
                CourseName = courseName,
                AttendanceWeight = attendanceWeight + "%",
                AttendanceGrade = attendanceGrade,
                TotalGrade = "" // 空着先
            };
            // 将CourseGrade对象添加到列表中
            coursegrade.Add(courseGrade);
        }



        private void MypgBar(int max)
        {
            getSchBtn.Text += ".";
            double stepSize = 1.0 / max;
            progressBar.Progress += stepSize;
        }

        class Course
        {
            public string Name { get; set; }
            public string Link { get; set; }
        }
        public class CourseGrade
        {
            public string CourseName { get; set; }   // 课程名字
            public string AttendanceWeight { get; set; }   // 平时分占比 (0-1之间的小数，表示百分比)
            public string AttendanceGrade { get; set; }    // 平时分
            public string TotalGrade { get; set; }        // 总成绩
        }

        private void comboBox3Picker_SelectedIndexChanged(object sender, EventArgs e)
        {
            Picker picker = (Picker)sender;

            if (picker.SelectedIndex != -1)
            {
                //string selectedOption = (string)picker.SelectedItem;
                string uid = (string)picker.SelectedItem;
                if (uid != "我选输入")
                {
                    textBox3.IsEnabled = false; // 禁用输入框
                }
                else
                {
                    textBox3.IsEnabled = true;
                    textBox2.IsEnabled = true;
                    textBox2.Text = "";
                    textBox3.Text = "";
                    return;
                }
                LoadCredentialsFromFile(uid);
            }
        }

        private async void Button_Clicked_2(object sender, EventArgs e)
        {
            string fileName = mainpath + "//myAllScore.html";
            if (!File.Exists(fileName))
            {
                await DisplayAlert("提示", "能不能先输账号密码获取？", "可以");

                return;
            }
            string pageContent = File.ReadAllText(fileName);
            Allscore(pageContent);
            string pageContent1 = Regex.Replace(pageContent, @"[\r\t\n]", "");
            // 使用正则表达式匹配指定的 td 标签，允许包含换行和空格字符
            string pattern = @"姓名</span> ：</td><td height=""16"" class=""td_left"">\s*<div align=""left"">\s*([\u4e00-\u9fa5]+)\s*</div>\s*</td>";
            MatchCollection matches = Regex.Matches(pageContent1, pattern, RegexOptions.Singleline);

            // 提取匹配项中的值
            foreach (Match match in matches)
            {
                studentname = match.Groups[1].Value.Trim();
            }
            getSchBtn.Text = "获取/更新成绩";

            // 跳转新页面
            await Navigation.PushAsync(new ScrScore() { Title = studentname + "'s 成绩" });
        }

        private void checkBox2_Toggled(object sender, ToggledEventArgs e)
        {
            bool isSwitchOn = e.Value; // 获取 Switch 控件的新状态

            textBox2.IsPassword = !isSwitchOn;
        }

        private async void Button_Clicked(object sender, EventArgs e)
        {
            // 弹窗确认是否删除所有数据
            bool userConfirmed = await DisplayAlert("确认删除", "是否确定删除所有数据？", "是", "取消");

            if (userConfirmed)
            {
                // 定义文件所在的目录
                string directoryPath = mainpath;

                // 删除目录下的所有文件
                string[] files = Directory.GetFiles(directoryPath);
                foreach (string file in files)
                {
                    File.Delete(file);
                }

                // 删除目录下的所有子目录和文件
                string[] subdirectories = Directory.GetDirectories(directoryPath);
                foreach (string subdirectory in subdirectories)
                {
                    Directory.Delete(subdirectory, true);
                }

                // 弹窗提示删除成功
                await DisplayAlert("提示", "删除成功", "确定");
                // 刷新页面
                await Navigation.PushAsync(new MainPage() { Title = "挂科！" });
            }
            else
            {
                // 用户点击了 "取消"，不执行删除操作

            }
        }

        [Obsolete]
        private async void CopyrightLabel_Tapped(object sender, EventArgs e)
        {
            string message = "本程序承诺：所有数据本地进行处理，不会主动收集、共享、转让你的信息至任何第三方\n\n";
            message += "若你认为开发者未遵守上述约定，或有其他的投诉建议、或未成年人个人信息保护相关问题，可通过以下方式与开发者联系；或者删除该软件。\n\n";
            message += "vanderwals@163.com\n\n";
            message += "本地数据目录：\n";
            message += "/data/user/0/com.companyname.scores\n\n";
            message += "开源地址：\n";
            message += "https://gitee.com/Big_M/score-inquiry.git";

            bool userClicked = await DisplayAlert("声明", message, "打开链接", "关闭");

            if (userClicked)
            {
                // 用户点击了 "打开链接"，在此处打开链接
                Device.OpenUri(new Uri("https://gitee.com/Big_M/score-inquiry.git"));
            }
        }

    }
}
